<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Topics tagged with cse api]]></title><description><![CDATA[A list of topics that have been tagged with cse api]]></description><link>https://community.secnto.com//tags/cse api</link><generator>RSS for Node</generator><lastBuildDate>Mon, 08 Jun 2026 19:54:51 GMT</lastBuildDate><atom:link href="https://community.secnto.com//tags/cse api.rss" rel="self" type="application/rss+xml"/><pubDate>Invalid Date</pubDate><ttl>60</ttl><item><title><![CDATA[Google Custom Search API Key and CX ID to be configured]]></title><description><![CDATA[@zaasmi said in Google Custom Search API Key and CX ID to be configured:

Would you like to show how to add a “Loading Spinner” to the HTML so users know the search is happening?

A loading spinner is essential for a good user experience. Without it, the user might think the app is broken while the Python backend is busy talking to Google’s servers.
Here is how to add a clean, CSS-only spinner that appears during the search and disappears once the image loads.
1. Add the CSS Spinner
Add this to the &lt;style&gt; section of your index.html. It creates a classic rotating ring.
/* The Spinner Animation */
.loader {
    border: 4px solid #f3f3f3;
    border-top: 4px solid #3498db;
    border-radius: 50%;
    width: 30px;
    height: 30px;
    animation: spin 1s linear infinite;
    display: none; /* Hidden by default */
    margin: 10px auto;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}


2. Update the HTML
Place the loader div right above your gallery so users see it immediately after clicking search.
&lt;div id="loader" class="loader"&gt;&lt;/div&gt;
&lt;div class="gallery" id="gallery"&gt;&lt;/div&gt;


3. Update the JavaScript Logic
Modify your performSearch function to toggle the loader’s visibility using display: block and display: none.
async function performSearch() {
    const query = document.getElementById('searchInput').value;
    const loader = document.getElementById('loader');
    const gallery = document.getElementById('gallery');

    if (!query) return;

    // 1. Show the loader
    loader.style.display = "block";

    try {
        const response = await fetch(`http://127.0.0.1:5000/search?q=${query}`);
        const data = await response.json();

        if (data.url) {
            const card = document.createElement('div');
            card.className = 'card';
            card.innerHTML = `&lt;img src="${data.url}"&gt;&lt;p&gt;${query}&lt;/p&gt;`;
            gallery.prepend(card);
        }
    } catch (error) {
        console.error("Error fetching image:", error);
    } finally {
        // 2. Hide the loader (whether it worked or failed)
        loader.style.display = "none";
    }
}



Visualizing the Feedback Loop
The loader bridges the gap between the user’s action and the server’s reaction.
Why this matters for your Google API
Because the Google Custom Search API can sometimes take 1-2 seconds to respond, a “silent” screen makes users click the button multiple times. Each click could potentially trigger a new API call, wasting your 100-query daily limit. The spinner tells the user: “I’m working, please wait.”
Final Pro-Tip: Debouncing
If you want to be extra safe, you can disable the “Search” button as soon as it’s clicked so the user cannot trigger multiple API requests until the current one finishes.
// Add this inside performSearch
document.querySelector('button').disabled = true;

// Re-enable it in the 'finally' block
document.querySelector('button').disabled = false;


]]></description><link>https://community.secnto.com//topic/2758/google-custom-search-api-key-and-cx-id-to-be-configured</link><guid isPermaLink="true">https://community.secnto.com//topic/2758/google-custom-search-api-key-and-cx-id-to-be-configured</guid><dc:creator><![CDATA[cyberian]]></dc:creator><pubDate>Invalid Date</pubDate></item></channel></rss>